﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Windows.Forms;

// ReSharper disable LoopCanBePartlyConvertedToQuery

namespace ServiceManager
{
    /// <summary>
    ///     Class Manager.
    /// </summary>
    public partial class Manager : Form
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Manager" /> class.
        /// </summary>
        public Manager()
        {
            this.InitializeComponent();
            this.ShowLog(@"安装器启动成功!");
        }

        /// <summary>
        ///     Handles the Click event of the BrowseBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void BrowseBtn_Click(object sender, EventArgs e)
        {
            this.openServiceFileDialog.Filter = @"(*.exe)|*.exe";
            this.openServiceFileDialog.FileName = "";
            this.openServiceFileDialog.Title = @"选择您要安装的服务程序";
            if (this.openServiceFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.ServiceDictory.Text = this.openServiceFileDialog.FileName;
            }
        }

        /// <summary>
        ///     Handles the Click event of the InstallBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void InstallBtn_Click(object sender, EventArgs e)
        {
            if (!this.Validate())
            {
                return;
            }
            string[] cmdline = { };
            string serviceFileName = this.ServiceDictory.Text.Trim();
            string serviceName = this.GetServiceName(serviceFileName);
            if (string.IsNullOrWhiteSpace(serviceName))
            {
                this.ShowLog(@"所选文件不是Windows服务!");
            }
            if (this.ServiceIsExisted(serviceName))
            {
                this.ShowLog(@"要安装的服务" + serviceName + "已经存在!");
            }
            TransactedInstaller transactedInstaller = new TransactedInstaller();
            AssemblyInstaller assemblyInstaller =
                new AssemblyInstaller(serviceFileName, cmdline)
                {
                    UseNewContext = true
                };

            transactedInstaller.Installers.Add(assemblyInstaller);
            transactedInstaller.Install(new Hashtable());
            this.ShowLog(@"服务" + serviceName + "安装成功!");
        }

        private void mBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string serviceFileName = (string)e.Argument;
            string[] cmdline = { };
            BackgroundWorker bw = (BackgroundWorker)sender;
            bw.ReportProgress(0, @"卸载服务已开始,请稍后....");
            TransactedInstaller transactedInstaller = new TransactedInstaller();
            AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
            transactedInstaller.Installers.Add(assemblyInstaller);
            transactedInstaller.Uninstall(null);
            bw.ReportProgress(0, "服务卸载成功!");
        }

        private void mBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.ShowLog((string)e.UserState);
            if ((string)e.UserState == "服务卸载成功!")
            {
                Process.Start(Assembly.GetExecutingAssembly().Location, this.ServiceDictory.Text.Trim());
                this.Close();
            }
        }

        /// <summary>
        ///     Handles the Click event of the RunBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void RunBtn_Click(object sender, EventArgs e)
        {
            if (!this.Validate())
            {
                return;
            }
            try
            {
                string serviceName = this.GetServiceName(this.ServiceDictory.Text.Trim());
                if (string.IsNullOrEmpty(serviceName))
                {
                    this.ShowLog(@"指定文件不是Windows服务!");
                    return;
                }
                if (!this.ServiceIsExisted(serviceName))
                {
                    this.ShowLog(@"指定启动的服务" + serviceName + "不存在.....");
                    return;
                }
                ServiceController service = new ServiceController(serviceName);
                if (service.Status != ServiceControllerStatus.Running
                    && service.Status != ServiceControllerStatus.StartPending)
                {
                    service.Start();
                    this.ShowLog(@"服务启动成功....");
                }
                else
                {
                    this.ShowLog(@"服务正在运行....");
                }
            }
            catch (Exception ex)
            {
                this.ShowLog(@"程序出现异常....");
                this.ShowLog(ex.Message);
            }
        }

        /// <summary>
        ///     Handles the Click event of the StopBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void StopBtn_Click(object sender, EventArgs e)
        {
            if (!this.Validate())
            {
                return;
            }
            try
            {
                string servieFileName = this.ServiceDictory.Text.Trim();
                string serviceName = this.GetServiceName(servieFileName);
                if (string.IsNullOrWhiteSpace(serviceName))
                {
                    this.ShowLog(@"指定的文件不是Windows服务!");
                    return;
                }
                if (!this.ServiceIsExisted(serviceName))
                {
                    this.ShowLog(@"要停止的服务不存在!");
                    return;
                }
                ServiceController service = new ServiceController(serviceName);
                if (service.Status == ServiceControllerStatus.Running)
                {
                    service.Stop();
                    this.ShowLog(@"服务停止成功!");
                }
                else
                {
                    this.ShowLog(@"服务停止失败!");
                }
            }
            catch (Exception ex)
            {
                this.ShowLog(@"服务停止出现异常....");
                this.ShowLog(ex.Message);
            }
        }

        /// <summary>
        ///     Handles the Click event of the UnInstallBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void UnInstallBtn_Click(object sender, EventArgs e)
        {
            if (!this.Validate())
            {
                return;
            }
            try
            {
                string serviceFileName = this.ServiceDictory.Text.Trim();
                string serviceName = this.GetServiceName(serviceFileName);
                if (string.IsNullOrWhiteSpace(serviceName))
                {
                    this.ShowLog(@"指定的文件不是Windows服务!");
                    return;
                }
                if (!this.ServiceIsExisted(serviceName))
                {
                    this.ShowLog(@"要卸载的服务不存在!");
                    return;
                }
                if (this.mBackgroundWorker.IsBusy)
                {
                    MessageBox.Show(@"当前进程正在卸载服务,请等待本实例操作结束!");
                    this.ShowLog(@"当前进程正在卸载服务,请等待本实例操作结束!");
                    return;
                }

                this.mBackgroundWorker.RunWorkerAsync(serviceFileName);
            }
            catch (Exception ex)
            {
                this.ShowLog(@"哎哟 我艹，出异常了!");
                this.ShowLog(ex.Message);
            }
        }

        #region 帮助方法

        /// <summary>
        ///     Gets the name of the service.
        /// </summary>
        /// <param name="serviceFileName">Name of the service file.</param>
        /// <returns>System.String.</returns>
        private string GetServiceName(string serviceFileName)
        {
            try
            {
                Assembly assembly = Assembly.LoadFrom(serviceFileName);
                Type[] types = assembly.GetTypes();
                // ReSharper disable once LoopCanBePartlyConvertedToQuery
                foreach (var myType in types)
                {
                    if (myType.IsClass && myType.BaseType == typeof(Installer))
                    {
                        FieldInfo[] fieldInfos =
                            myType.GetFields(
                                BindingFlags.NonPublic | BindingFlags.Public
                                | BindingFlags.Default | BindingFlags.Instance
                                | BindingFlags.Static);
                        // ReSharper disable once LoopCanBePartlyConvertedToQuery
                        foreach (var myFieldInfo in fieldInfos)
                        {
                            if (myFieldInfo.FieldType == typeof(ServiceInstaller))
                            {
                                ServiceInstaller serviceInstaller = (ServiceInstaller)myFieldInfo.GetValue(Activator.CreateInstance(myType));
                                return serviceInstaller.ServiceName;
                            }
                        }
                    }
                }
                return "";
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        ///     Services the is existed.
        /// </summary>
        /// <param name="serviceName">Name of the service.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool ServiceIsExisted(string serviceName)
        {
            return ServiceController
                .GetServices()
                .ToList()
                .FirstOrDefault(s =>
                    s.ServiceName.ToLower().Trim() == serviceName.ToLower().Trim())
                   != null;
        }

        /// <summary>
        ///     Shows the log.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        private void ShowLog(string msg)
        {
            this.MessageShow.AppendText(msg + "\r\n");
        }

        private bool Validate()
        {
            if (string.IsNullOrWhiteSpace(this.ServiceDictory.Text.Trim()))
            {
                this.ShowLog(@"您没有选择服务安装程序!");
                return false;
            }
            if (!File.Exists(this.ServiceDictory.Text.Trim()))
            {
                this.ShowLog(@"所选exe文件路径不合法!");
                return false;
            }
            if (!this.ServiceDictory.Text.Trim().EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
            {
                this.ShowLog(@"您选择的不是windows服务程序!");
                return false;
            }
            return true;
        }

        #endregion 帮助方法
    }
}